import { Dispute, DisputeKind, DisputeService, DisputeStatus, ItemStatus } from "@mallfoundry/order"
import { PageList } from "@mallfoundry/shared/data"
import { Badge, Button, Card, Col, DatePicker, Form, Input, Pagination, Radio, Row, Select, Space, Spin, Table } from "antd"
import { RadioChangeEvent } from "antd/lib/radio"
import { ColumnProps } from "antd/lib/table"
import classNames from "classnames"
import * as dayjs from "dayjs"
import * as _ from "lodash"
import * as React from "react"
import { useEffect, useState } from "react"
import { Link, useHistory, useLocation, useParams } from "react-router-dom"
import Page from "../../components/page"
import classes from "./orders-dispute-list.module.scss"

const { RangePicker } = DatePicker

class OrderDisputeColumn {
  public storeId: string = ""
  public orderId: string = ""
  public refundId: string = ""
  public name: string = ""
  public itemStatus: string = ""
  public amount: string = ""
  public itemAmount: string = ""
  public appliedTime: string = ""
  public status: string = ""
  public itemsCount: number = 0
}

const columns: ColumnProps<OrderDisputeColumn>[] = [
  {
    title: "商品",
    dataIndex: "name",
    key: "name",
  },
  {
    title: "收货状态",
    dataIndex: "itemStatus",
    key: "itemStatus",
    width: "160px",
    align: "center",
    render: (itemStatus) => (<>
      {ItemStatus.Received === itemStatus && "已收到货"}
      {ItemStatus.NotReceived === itemStatus && "未收到货"}
    </>),
  },
  {
    title: "订单金额(元)",
    dataIndex: "itemAmount",
    key: "itemAmount",
    width: "160px",
    align: "center",
  },
  {
    title: "退款金额(元)",
    dataIndex: "amount",
    key: "amount",
    width: "160px",
    align: "center",
  },
  {
    title: "申请时间",
    dataIndex: "appliedTime",
    key: "appliedTime",
    width: "160px",
    align: "center",
  },
  {
    title: "售后状态",
    dataIndex: "status",
    key: "status",
    width: "160px",
    align: "center",
    render: (status) => (<>
      {DisputeStatus.Applying === status && "退款申请待商家处理"}
      {DisputeStatus.Reapplying === status && "退款申请待商家处理"}
      {DisputeStatus.Cancelled === status && "退款取消"}
      {DisputeStatus.Disapproved === status && "商家不同意退款申请，待买家处理"}
      {DisputeStatus.Pending === status && "商家同意退款申请，退款中"}
      {DisputeStatus.Succeeded === status && "退款成功"}
      {DisputeStatus.Failed === status && "退款失败"}
    </>),
  },
  {
    title: "操作",
    dataIndex: "status",
    key: "status",
    width: "160px",
    align: "right",
    render: (status, row) => {
      return <Link to={`/stores/${row.storeId}/orders/${row.orderId}/refunds/${row.refundId}`}>
        {
          (DisputeStatus.Pending === status ||
            DisputeStatus.Succeeded === status ||
            DisputeStatus.Failed === status
          ) ? "查看详情" : "处理退款"
        }
      </Link>
    },
  },
]

interface OrderDisputeProps {
  dispute: Dispute
}

function OrderDispute(props: OrderDisputeProps) {
  const { dispute } = props
  const dataSource = [_.assign(new OrderDisputeColumn(), dispute, {
    storeId: dispute.storeId,
    orderId: dispute.orderId,
    refundId: dispute.id,
    itemStatus: dispute.itemStatus,
    appliedTime: dispute.appliedTime,
    status: dispute.status,
    itemAmount: dispute.itemAmount,
  })]
  return (
    <div className={classes.OrderDispute}>
      <Table rowKey="id" size="small"
             showHeader={false} pagination={false}
             columns={columns} dataSource={dataSource}
             title={() => <Row justify="space-between">
               <Col span={18}>
                 <Space>
                   <span>售后编号：{dispute.id}</span>
                   <span>订单编号：{dispute.orderId}</span>
                   {dispute.kind === DisputeKind.OnlyRefund && <Badge color="red" text="仅退款"/>}
                   {dispute.kind === DisputeKind.ReturnRefund && <Badge color="blue" text="退货退款"/>}
                 </Space>
               </Col>
             </Row>}/>
    </div>
  )
}


export default function OrdersDisputeList() {
  const history = useHistory()
  const { storeId = "" } = useParams<{ storeId: string }>()
  const location = useLocation()
  const searchParams = new URLSearchParams(location.search)
  const page = searchParams.get("page") ?? 1
  const limit = searchParams.get("limit") ?? 20
  const orderId = searchParams.get("order_id") ?? ""
  const ids = searchParams.get("ids") ?? ""
  const kind = searchParams.get("kind") ?? ""
  const statuses = searchParams.get("statuses") ?? ""
  const appliedTimeMin = searchParams.get("applied_time_min") ?? ""
  const appliedTimeMax = searchParams.get("applied_time_max") ?? ""
  const sort = searchParams.get("sort") ?? "applied_time:desc"
  const timestamp = searchParams.get("timestamp") ?? ""

  // states
  const [customAppliedTimes, setCustomAppliedTimes] = useState(0)
  const [loading, setLoading] = useState(false)
  const [pageDisputes, setPageDisputes] = useState(PageList.empty<Dispute>())
  const [form] = Form.useForm()

  const layout = {
    labelCol: { span: 6 },
    wrapperCol: { span: 18 },
  }

  const disputes = pageDisputes.elements

  useEffect(refreshDisputes, [storeId, orderId, ids, kind, statuses, page, limit, sort, timestamp])
  useEffect(() => {
    form.setFieldsValue({
      orderId, ids, kind, statuses,
      appliedTimes: [
        appliedTimeMin ? dayjs(appliedTimeMin) : undefined,
        appliedTimeMax ? dayjs(appliedTimeMax) : undefined,
      ],
    })
    handleSetCustomAppliedTimes([appliedTimeMin, appliedTimeMax])
  }, [form, orderId, ids, kind, statuses, appliedTimeMin, appliedTimeMax])

  function refreshDisputes() {
    setLoading(true)
    DisputeService.getOrderDisputes(
      DisputeService.createDisputeQuery()
        .toBuilder()
        .page(page).limit(limit)
        .sort(sort)
        .storeId(storeId)
        .ids(ids)
        .kinds(kind)
        .statuses(statuses)
        .build(),
    )
      .then(setPageDisputes)
      .finally(() => setLoading(false))
  }

  function handleChangeAppliedTimes(e: RadioChangeEvent) {
    const aCustomAppliedTimes = e.target.value
    setCustomAppliedTimes(aCustomAppliedTimes)
    if (aCustomAppliedTimes === -7) {
      form.setFieldsValue({ appliedTimes: [dayjs().add(-7, "day"), dayjs().add(1, "day")] })
    } else if (aCustomAppliedTimes === -30) {
      form.setFieldsValue({ appliedTimes: [dayjs().add(-30, "day"), dayjs().add(1, "day")] })
    } else if (aCustomAppliedTimes === -90) {
      form.setFieldsValue({ appliedTimes: [dayjs().add(-90, "day"), dayjs().add(1, "day")] })
    }
  }

  function handleSetCustomAppliedTimes(dateStrings: [string, string]) {
    const [dateStart, dateEnd] = dateStrings
    const tomorrow = dayjs().add(1, "day").format("YYYY-MM-DD")
    const in7day = dayjs().add(-7, "day").format("YYYY-MM-DD")
    const in30day = dayjs().add(-30, "day").format("YYYY-MM-DD")
    const in90day = dayjs().add(-90, "day").format("YYYY-MM-DD")
    if (dateStart === in7day && dateEnd === tomorrow) {
      setCustomAppliedTimes(-7)
    } else if (dateStart === in30day && dateEnd === tomorrow) {
      setCustomAppliedTimes(-30)
    } else if (dateStart === in90day && dateEnd === tomorrow) {
      setCustomAppliedTimes(-90)
    } else {
      setCustomAppliedTimes(1)
    }
  }

  function handleSearch() {
    form.validateFields()
      .then(values => {
        const { orderId, ids, statuses, kind, appliedTimes } = values
        if (orderId) {
          searchParams.set("order_id", orderId)
        } else {
          searchParams.delete("order_id")
        }
        if (ids) {
          searchParams.set("ids", ids)
        } else {
          searchParams.delete("ids")
        }
        if (appliedTimes) {
          const [appliedTimeMin, appliedTimeMax] = appliedTimes
          if (appliedTimeMin) {
            searchParams.set("applied_time_min", dayjs(appliedTimeMin).format("YYYY-MM-DD"))
          } else {
            searchParams.delete("applied_time_min")
          }
          if (appliedTimeMax) {
            searchParams.set("applied_time_max", dayjs(appliedTimeMax).format("YYYY-MM-DD"))
          } else {
            searchParams.delete("applied_time_max")
          }
        } else {
          searchParams.delete("applied_time_min")
          searchParams.delete("applied_time_max")
        }
        if (kind) {
          searchParams.set("kind", kind)
        } else {
          searchParams.delete("kind")
        }
        if (statuses) {
          searchParams.set("statuses", statuses)
        } else {
          searchParams.delete("statuses")
        }
        searchParams.set("timestamp", Date.now().toString())
        history.replace(_.assign(location, {
          search: `?${searchParams.toString()}`,
        }))
      })
  }

  function handleReset() {
    history.push(_.assign(location, {
      search: ``,
    }))
  }

  return (
    <div className={classes.OrdersDisputeList}>
      <Page.Header title="售后维权" ghost={false}/>
      <Page.Content>
        <Card>
          <Row gutter={[16, 16]}>
            <Col span={24}>
              <Card className={classes.FilterBar} bordered={false}>
                <Form {...layout} form={form}>
                  <Row>
                    <Col span={6}>
                      <Form.Item name="orderId" label="订单编号">
                        <Input placeholder="请输入订单编号" allowClear/>
                      </Form.Item>
                    </Col>
                  </Row>
                  <Row>
                    <Col span={6}>
                      <Form.Item label="申请时间" name="appliedTimes">
                        <RangePicker style={{ width: "100%" }}
                                     onChange={(dates, dateStrings) => handleSetCustomAppliedTimes(dateStrings)}/>
                      </Form.Item>
                    </Col>
                    <Col span={6}>
                      <Radio.Group style={{ marginLeft: "8px" }} value={customAppliedTimes} onChange={handleChangeAppliedTimes}>
                        <Space>
                          <Radio.Button value={-7} className={classes.PlacedDateButton}>近7天</Radio.Button>
                          <Radio.Button value={-30} className={classes.PlacedDateButton}>近30天</Radio.Button>
                          <Radio.Button value={-90} className={classes.PlacedDateButton}>近90天</Radio.Button>
                        </Space>
                      </Radio.Group>
                    </Col>
                  </Row>
                  <Row>
                    <Col span={6}>
                      <Form.Item name="ids" label="售后编号">
                        <Input placeholder="请输入售后编号" allowClear/>
                      </Form.Item>
                    </Col>
                    <Col span={6}>
                      <Form.Item name="kind" label="售后方式">
                        <Select placeholder="请选择类型">
                          <Select.Option value="">全部</Select.Option>
                          <Select.Option value={DisputeKind.OnlyRefund}>仅退款</Select.Option>
                          <Select.Option value={DisputeKind.ReturnRefund}>退货退款</Select.Option>
                        </Select>
                      </Form.Item>
                    </Col>
                    <Col span={6}>
                      <Form.Item name="statuses" label="售后状态">
                        <Select placeholder="请选择状态">
                          <Select.Option value="">全部</Select.Option>
                          <Select.Option
                            value={[DisputeStatus.Applying, DisputeStatus.Reapplying].join(",")}>退款申请待商家处理</Select.Option>
                          <Select.Option value={DisputeStatus.Disapproved}>商家不同意退款申请，待买家处理</Select.Option>
                          <Select.Option value={DisputeStatus.Succeeded}>退款成功</Select.Option>
                          <Select.Option value={DisputeStatus.Failed}>退款失败</Select.Option>
                        </Select>
                      </Form.Item>
                    </Col>
                  </Row>
                  <Row>
                    <Col span={6}>
                      <Row>
                        <Col offset={6}>
                          <Space>
                            <Button type="primary" onClick={handleSearch} loading={loading}>筛选</Button>
                            <Button onClick={handleReset}>重置</Button>
                          </Space>
                        </Col>
                      </Row>
                    </Col>
                  </Row>
                </Form>
              </Card>
            </Col>
          </Row>
          <Row gutter={[16, 16]} justify="space-between">
            <Col>
              <Radio.Group value={statuses} onChange={e => {
                const statuses = e.target.value
                if (statuses) {
                  searchParams.set("statuses", statuses)
                } else {
                  searchParams.delete("statuses")
                }
                history.push(_.assign(location, {
                  search: `?${searchParams.toString()}`,
                }))
              }}>
                <Radio.Button value="">全部</Radio.Button>
                <Radio.Button value={[DisputeStatus.Applying, DisputeStatus.Reapplying].join(",")}>待商家处理</Radio.Button>
                <Radio.Button value={[DisputeStatus.Disapproved].join(",")}>待买家处理</Radio.Button>
              </Radio.Group>
            </Col>
            <Col>
              <Radio.Group buttonStyle="solid" value={sort} onChange={e => {
                const sort = e.target.value
                if (sort) {
                  searchParams.set("sort", sort)
                } else {
                  searchParams.delete("sort")
                }
                history.push(_.assign(location, {
                  search: `?${searchParams.toString()}`,
                }))
              }}>
                <Radio.Button value="applied_time:desc">按最近申请排序</Radio.Button>
                <Radio.Button value="applying_expired_time:asc">按临近超时排序</Radio.Button>
              </Radio.Group>
            </Col>
          </Row>
          <Row gutter={[16, 16]}>
            <Col span={24}>
              <Spin spinning={loading}>
                <Table className={classNames({
                  [classes.OrdersDisputeTableHeader]: !_.isEmpty(disputes),
                })} columns={columns} pagination={false}/>
                {
                  _.map(disputes, aDispute => <OrderDispute key={aDispute.id} dispute={aDispute}/>)
                }
              </Spin>
            </Col>
          </Row>
          {
            !_.isEmpty(disputes) &&
            <Row justify="end">
              <Col>
                <Pagination current={_.toNumber(page)}
                            pageSize={_.toNumber(limit)}
                            showSizeChanger
                            pageSizeOptions={["10", "20", "50", "100"]}
                            total={pageDisputes.totalSize}
                            showTotal={total => `共 ${total} 条`}
                            onChange={(page, pageSize) => {
                              if (page) {
                                searchParams.set("page", _.toString(page))
                              } else {
                                searchParams.delete("page")
                              }
                              if (pageSize) {
                                searchParams.set("limit", _.toString(pageSize))
                              } else {
                                searchParams.delete("limit")
                              }
                              history.push(_.assign(location, {
                                search: `?${searchParams.toString()}`,
                              }))
                            }}/>
              </Col>
            </Row>
          }
        </Card>
      </Page.Content>
    </div>
  )
}
